package com.pubinfo.passbook.data.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.pubinfo.passbook.common.entity.TPassbookPersionInfo;
import com.pubinfo.passbook.common.mapper.TSubsidiaryPrivateKeyMapper;
import com.pubinfo.passbook.common.model.bo.SubsidiaryInfo;
import com.pubinfo.passbook.common.model.constant.RedisKey;
import com.pubinfo.passbook.common.model.dubbo.ESBServiceData;
import com.pubinfo.passbook.common.model.http.User.*;
import com.pubinfo.passbook.common.model.vo.base.JsonResult;
import com.pubinfo.passbook.common.service.dubbo.DubboService;
import com.pubinfo.passbook.common.service.master.*;
import com.pubinfo.passbook.common.service.request.financial.RequestFinancialServer;
import com.pubinfo.passbook.common.service.cache.JedisManage;
import com.pubinfo.passbook.common.utils.financial.SignUtil;
import com.pubinfo.passbook.data.service.ProvingUserService;
import com.pubinfo.passbook.data.service.TFileInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
@Service
public class ProvingUserServiceImpl implements ProvingUserService {
  
  @Autowired
  TPassbookService passbookService;
  @Autowired
  private TSubsidiaryPrivateKeyMapper keyMapper;
  @Autowired
  JedisManage redisService;
  @Autowired
  TPassbookPersionInfoService persionInfoService;
  
  @Autowired
  RequestFinancialServer financialServer;
  
  @Autowired
  TFileInfoService tFileInfoService;
  
  @Autowired
  TRuleGenusService genusService;
  @Autowired
  DubboService vatService;
  
  @Override
  public String provingUser(String str) {
    ProvingUser user = check(str, ProvingUser.class);
    String certName = redisService.getStr(RedisKey.PERSION_KEY + user.getUsercode());
    if (user == null) {
      return UserResult.error(UserResultCode.FAILED);
    }
    if (StringUtils.isNotBlank(certName)) {
      
      if (user.getUsername().equalsIgnoreCase(certName)) {
        return UserResult.success(user);
      }
    } else {
      //再查询人力接口,是否存在
      JsonResult<Collection<ESBServiceData.CertDetail>> jsonResult = vatService.getPersonsDetailByAcct(new ESBServiceData.Cert(user.getUsercode()));
      if (!CollectionUtils.isEmpty(jsonResult.getResult())) {
        return UserResult.success(user);
      }
    }
    //查询是否为供属
    if (genusService.isGenus(user.getUsercode())) {
      return UserResult.success(user);
    }
    
    return UserResult.error(UserResultCode.FAILED);
  }
//  @Override
//  public String provingUser(String str) {
//    ProvingUser user = check(str, ProvingUser.class);
//
//    String organization = redisService.getStr("queues_dzpj");
//    if (StringUtils.isNotBlank(organization) && user != null) {
//      JSONObject jsonObject = JSONObject.parseObject(organization);
//      List<TbCert> tbCerts = JSON.parseArray(JSONObject.toJSONString(JSONPath.eval(jsonObject, "$.context.tbCert")), TbCert.class);
//      if (CollectionUtils.isEmpty(tbCerts)) {
//        return UserResult.error(UserResultCode.SYSTEM_ERROR);
//      }
//      Long startTime = System.currentTimeMillis();
//      Boolean isExist = tbCerts.stream().anyMatch(m -> user.getUsercode().equalsIgnoreCase(m.getCertNo()) && user.getUsername().equalsIgnoreCase(m.getCertName()));
//      log.info("执行时间" + (System.currentTimeMillis() - startTime) + "ms");
//      if (isExist) {
//        return UserResult.success(user);
//      }
//    }
//
//    return UserResult.error(UserResultCode.FAILED);
//  }
  
  private <T> T check(String str, Class<T> cla) {
    T user = null;
    if (StringUtils.isNotBlank(str)) {
      JSONObject object = JSONObject.parseObject(str);
      String signature = object.getString("signature");
      String payloadStr = object.getString("payload");
      try {
        String payload = new String(new BASE64Decoder().decodeBuffer(payloadStr), StandardCharsets.UTF_8);
        String enterId = object.getString("instCode");
        String timestamp = object.getString("timestamp");
        String nonce = object.getString("nonce");
        List<SubsidiaryInfo> subsidiaryInfos = keyMapper.listFinAllSubsidiaryInfo(enterId);
        if (CollectionUtils.isNotEmpty(subsidiaryInfos)) {
          SubsidiaryInfo info = subsidiaryInfos.get(0);
          String dataContent = enterId + payloadStr + timestamp + nonce;
          String mySignature = SignUtil.sign(info.getPrivateKey(), info.getPassword(), dataContent);
          if (mySignature.equalsIgnoreCase(signature)) {
            user = JSONObject.toJavaObject(JSON.parseObject(payload), cla);
          }
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    return user;
  }
  
  @Override
  public String receiveInvoiceList(String str) {
    EInvoice eInvoice = check(str, EInvoice.class);
    if (eInvoice != null) {
  
      List<EInvoiceId> list = eInvoice.getEInvoiceList();
      if (CollectionUtils.isEmpty(list)) {
        return UserResult.error(UserResultCode.PARAM_ILLEGAL);
      }
      EInvoiceId eInvoiceId = list.get(0);
      Integer count = String.valueOf(eInvoiceId).indexOf("null");
      TPassbookPersionInfo info = new TPassbookPersionInfo(eInvoice);
      if (count == 0) {
        info.setIsSucceed(2);
      }
      log.info("接收票据:" + info);
      persionInfoService.save(info);
      //   ReceiveInvoiceThread invoiceThread = new ReceiveInvoiceThread(eInvoice,keyMapper,passbookService,financialServer,persionInfoService);
      //  invoiceThread.start();
      return UserResult.success(UserResultCode.SUCCESS);
    }
  
    return UserResult.error(UserResultCode.PARAM_ILLEGAL);
  }
  
  @Override
  public String getSignature(String username, String userCode, String enterId) {
    List<SubsidiaryInfo> subsidiaryInfos = keyMapper.listFinAllSubsidiaryInfo(enterId);
    if (CollectionUtils.isNotEmpty(subsidiaryInfos)) {
      SubsidiaryInfo info = subsidiaryInfos.get(0);
  
      String param = "{\n" +
          "  \n" +
          "  \"einvoiceList\": [\n" +
          "    {\n" +
          "      \"eInvoiceId\": \"template_czpj_330401_002000000312104033\" \n" +
          "    }\n" +
          "  ],\n" +
          "  \"enterId\": \"" + enterId + "\",\n" +
          "  \"usercode\": \"" + userCode + "\",\n" +
          "  \"username\": \"" + username + "\"}";
      JSONObject request = JSON.parseObject(param);
      String payload = new BASE64Encoder().encode((JSONObject.toJSONString(request)).getBytes(StandardCharsets.UTF_8));
      payload = payload.replace("\r\n", "");
      String nonce = RandomUtil.randomNumbers(6);
      long stamp = System.currentTimeMillis() / 1000;
      String dataContent = enterId + payload + stamp + nonce;
      String signature = SignUtil.sign(info.getPrivateKey(), info.getPassword(), dataContent);
      JSONObject object = new JSONObject();
      object.put("instCode", enterId);
      object.put("payload", payload);
      object.put("timestamp", stamp);
      object.put("nonce", nonce);
      object.put("signature", signature);
  
      return object.toJSONString();
    }
    return null;
  }
  
}
